import React, { memo, useEffect } from "react"
import "./style/index.css"
import useSetState from "@/hooks/useSetState"
import useSetRef from "@/hooks/useSetRef.js"
import { IconLoading } from "@/components/icon"

/**
 * 按钮
 * @param {object} props
 * @param {'primary' | 'secondary' | 'dashed' | 'text' | 'outline'} [props.type = secondary] 按钮状态 主要按钮、次级按钮、虚框按钮、文字按钮、线性按钮
 * @param {React.ReactNode} [props.icon=null] 按钮图标
 * @param {'circle' | 'round' | 'square'} [props.shape = square] 按钮形状 circle-圆形 round-全圆角 square-长方形
 * @param {'mini' | 'small' | 'default' | 'large'} [props.size = default] 按钮的尺寸 24px/28px/32px/36px
 * @param {'warning' | 'danger' | 'success' | 'default'} [props.status = default] 按钮状态
 * @param {boolean} [props.disabled = false] 是否禁用
 * @param {boolean} [props.loading = false] 是否是加载状态
 * @param {boolean} [props.long] 按钮宽度随容器自适应
 * @param {string | string[]} [props.className] 节点类名
 * @param {CSSProperties} [props.style = {}] 节点样式
 * @param {'button' | 'submit' | 'reset'} [props.htmlType = button] 按钮原生的 html type 类型
 * @param {string} [props.href] 添加跳转链接，设置此属性，button表现跟a标签一致
 * @param {"_self" | "_blank"} [props.target = _self] a 链接的 target 属性，href 存在时生效
 * @param {boolean} [props.wave = true] 波纹效果
 * @param {Function} [props.onClick = (e:Event) => void] 点击按钮的回调
 * @param {React.RefObject} [props.ref]
 * @returns {React.ReactNode}
 */
const Button = memo((props) => {
    const {
        type = "secondary", icon = null, shape = "square", size = "default", status = "default", disabled = false, ref: originButtonRef,
        loading = false, long, htmlType = "button", href = "", target = "", className = "", style = {}, wave = true, children
    } = props
    const [state, setState] = useSetState({
        isMouseDown: false,
        rippleStyle: {} // 波纹样式
    })
    const [ref, setRef] = useSetRef({
        isMouseDowning: false,
        mouseDownTimer: null,
        buttonRef: null
    })
    const isSquare = shape === "square"
    useEffect(() => {
        getRippleStyle()
    }, [])
    const getRippleStyle = () => {
        if (!wave) return
        const { buttonRef } = ref
        const style = {
            "--bg-color": "",
            "--opacity": ["secondary", "dashed'"].includes(type) ? 0.5 : 0.1,
            "--width": "",
            "--border-radius": (isSquare ? 4 : 9999) + "px"
        }
        if (buttonRef && type !== "text") {
            const computedStyle = window.getComputedStyle(buttonRef)
            let color = computedStyle.backgroundColor || ""
            if (type === "outline") {
                color = computedStyle.borderColor || ""
            }
            const height = parseInt(computedStyle.height)
            const width = parseInt(computedStyle.width) + height * 0.35
            style["--width"] = width + "px"
            style["--bg-color"] = color
        }
        setState({ rippleStyle: style })
    }
    const onMouseDown = () => {
        if (ref.isMouseDowning || disabled || !wave) return
        clearTimeout(ref.mouseDownTimer)
        setRef({ isMouseDowning: true, mouseDownTimer: null })
        setState({ isMouseDown: true })
        const mouseDownTimer = setTimeout(() => {
            setState({ isMouseDown: false })
            setRef({ isMouseDowning: false, mouseDownTimer: null })
        }, 500)
        setRef({ mouseDownTimer })
    }
    const onClick = (event) => {
        event.preventDefault()
        if (href) {
            if (target === '_blank') {
                return window.open(href);
            }
            return window.location.href = href;
        }
        props.onClick?.()
    }
    const { isMouseDown, rippleStyle } = state

    const render = () => {
        return (
            <button
                className={className + `${!children && (icon || loading) ? "next-btn-icon-only" : ""} next-btn-size-${size} next-btn-${type}
                next-btn-status-${status} ${disabled && "next-btn-disabled"} ${loading && "next-btn-loading"} next-btn-shape-${shape} ${long && "next-btn-long"}
                relative next-btn font-normal outline-none select-none appearance-none cursor-pointer whitespace-nowrap box-border transition-alls`}
                style={{
                    ...style,
                    "--group-border-right": `var(${type === "primary" ? "--color-primary-4" : "--color-neutral-3"})`,
                    "--border-radius": ""
                }}
                onMouseDown={onMouseDown}
                onClick={onClick}
                ref={ref => {
                    setRef({ buttonRef: ref })
                    originButtonRef?.(ref)
                }}
                type={htmlType}
            >
                {
                    isMouseDown && <span className="ripple" style={rippleStyle}></span>
                }
                {loading ? <IconLoading spin /> : icon}
                {
                    children && <span className="content">{children}</span>
                }
            </button>
        )
    }
    return render()
})
Button.Group = memo((props) => {
    return (
        <div className="inline-flex items-center justify-center next-btn-group">
            {props.children}
        </div>
    )
})

export default Button